package kgame5.k3d.core.obj3d.node3d.impl.mesh.animator.channel {
import kgame5.k3d.core.obj3d.node3d.impl.mesh.animator.Animator3D;
import kgame5.k3d.core.obj3d.node3d.impl.mesh.animator.parts.KeyFrame3D;

import flash.utils.Dictionary;

/**
 * @author kangkai
 * 0__1__2__3__4
 * 其中currentFrame最多是3，如果检测到了是3,则变成0。所以为了动画连续，0和4是相同的
 */
public class AbstractChannel3D {
		
		public static const 
			EOA_COMMAND_GOTO:String="GOTO",//跳转到某个动作
		 	EOA_COMMAND_LOOP:String="LOOP",//循环
		 	EOA_COMMAND_STOP:String="STOP";//停止
	
		
	
		
		//动画播放结束后该播放什么
		public var eoaCommand:String;//这个是说当动画播放完毕后该执行的做作
		public var eoaCommandParam:String;//命令参数。只是表示要跳转到的动作的id
		
		//能够跳转到本动作的动作表
		public var dictFromActionNames:Dictionary=new Dictionary();
		
		/** The target for this animation channel. */
		public var target:Animator3D;
		
		/** Name of the channel. */
		public var name:String;
		
		/** Array of keyframes. */	
		public var keyFrames:Array;
		
		/** Start time in seconds. */
		public var startTime:Number;
		
		/** End time in seconds. */
		public var endTime:Number;
		
		/** Current time in seconds. */
		public var currentTime:Number;
		
		/** Current keyframe as index into keyFrames array. */
		public var currentIndex:int;
		
		/** Next keyframe as index into keyFrames array. */
		public var nextIndex:int;
		
		/** Current keyframe. */
		public var currentKeyFrame:KeyFrame3D;
		
		/** Next keyframe. */
		public var nextKeyFrame:KeyFrame3D;
		
		/** Total duration in seconds. */
		public var durationSec:Number;
		
		//为了减少出发而坐，因为progress=currentSet/durationSec
		public var invertDurationSec:Number;
		
		/** Value between 0 and 1 indicating current position inbetween current and next keyframe. */
		public var frameAlpha:Number;
		
		/** Duration of the interval between current and next frame in seconds. */
		public var frameDuration:Number;
		
		/**
		 * Constructor.
		 * 
		 * @param	parent
		 * @param	target
		 * @param	name
		 */ 
		public function AbstractChannel3D(target:Animator3D, name:String = null)
		{
			this.target = target;
			this.name = name;
			this.startTime = this.endTime = 0;
			this.keyFrames = new Array();
			this.currentKeyFrame =this.nextKeyFrame = null;
			this.currentIndex = this.nextIndex = -1;
			this.frameAlpha = 0;
		}
		
		/**
		 * Adds a new keyframe.
		 * 
		 * @param	keyframe
		 * 
		 * @return	The added keyframe.
		 */ 
		public function addKeyFrame(keyframe:KeyFrame3D):void
		{
			if(this.keyFrames.length>0)
			{
				this.startTime = Math.min(this.startTime, keyframe.time);
				this.endTime = Math.max(this.endTime, keyframe.time);
			}
			else
			{
				this.startTime = this.endTime = keyframe.time;
			}
			
			this.durationSec = this.endTime - this.startTime;
			this.invertDurationSec=1/durationSec;
			
			this.keyFrames.push(keyframe);
			this.keyFrames.sortOn("time", Array.NUMERIC);
			
		}
		
		/**
		 * Updates this channel.
		 * 
		 * @param	keyframe
		 */ 
		public function updateToFrame(keyframe:uint):void
		{	
			if(this.keyFrames.length==0)
			{
				return;
			}
			
			currentIndex = keyframe;
			currentIndex = currentIndex < this.keyFrames.length - 1 ? currentIndex : 0;
			
			nextIndex = currentIndex + 1;
			
			currentKeyFrame = this.keyFrames[currentIndex];
			nextKeyFrame = nextIndex < this.keyFrames.length ? this.keyFrames[nextIndex] : null;
			
			frameDuration = nextKeyFrame ? nextKeyFrame.time - currentKeyFrame.time : currentKeyFrame.time;
			
			frameAlpha = 0;
			currentTime = currentKeyFrame.time;
		}
		
		/**
		 * Updates this channel by time.
		 * 这个time是个比例,20%
		 * 这个比updateToFrame消耗要稍微高一些
		 */ 
		public function updateToTime(progress:Number):void
		{	
			currentIndex = Math.floor((this.keyFrames.length-1) * progress);
			
			currentIndex = currentIndex < this.keyFrames.length - 1 ? currentIndex : 0;
			nextIndex = currentIndex + 1;
			
			currentKeyFrame = this.keyFrames[currentIndex];
			nextKeyFrame = nextIndex < this.keyFrames.length ? this.keyFrames[nextIndex] : null;
			
			frameDuration = nextKeyFrame ? nextKeyFrame.time - currentKeyFrame.time : currentKeyFrame.time;
			
			currentTime = progress * this.durationSec;
			
			frameAlpha = (currentTime - currentKeyFrame.time) / frameDuration;
			
			// clamp between 0 and 1
			frameAlpha = frameAlpha < 0 ? 0 : frameAlpha;
			frameAlpha = frameAlpha > 1 ? 1 : frameAlpha;
		}
	}
}

